package com.runa.rccprotocol.dto.langkabo;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.comm.dto.newComm.HotMeterVO;
import com.runa.monitor.comm.dto.newComm.ValveVO;
import com.runa.protocol.dto.IResponseData;
import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;
import com.runa.rccprotocol.dto.ConcentratorRequestData;
import com.runa.rccprotocol.dto.DynamicCheckInterface;
import com.runa.rccprotocol.dto.runa.RunaConcenResponseData;
import com.runa.rccprotocol.dto.runa.RunaFrameSequence;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

/**
 * @author diandian
 * @Date 2022/5/9 13:20
 */
@Slf4j
public class LangKaBoEquRequestData extends ConcentratorRequestData {
    public LangKaBoEquRequestData(String address) {
        super(address);
    }

    @Override
    public byte[] getData() {
        return requestData;
    }

    private byte[] requestData;

    private DynamicCheckInterface checkInterface;

    public void readElectric() {
        String s = "68 28 00 28 00 68 41 02 37 01 00 00 10 F0 00 00 01 00 00 00 00 00 48 21 14 00 FE FE FE FE 68 AA AA AA AA AA AA 68 11 04 33 33 33 33 AD 16 61 16";
        requestData = ByteUtil.hexStringToByte(s);
//        ByteUtil.tenstringToBcd(requestData, meterNo, 1, false);
//        requestData[14] = ByteUtil.sum(requestData, 0, 14);
        setHaveResult(true);
    }

    public void setNodeEquArchive(String serial, String factoryName) {
//        String hexS="68590059006841023701000004FF00000201112233440100000000000000001234567140420287FFFF01404202877714004821312D312D310000000000000000000000000000000000000000000000000000008cc32800f49428008cc328000D16";
        String hexS = "68590059006841023701000004FF00000201112233440100000000000000001234567140420287FFFF014042028777LLLL4821312D312D310000000000000000000000000000000000000000000000000000008cc32800f49428008cc328000D16";
        if (factoryName.equalsIgnoreCase("汇中")) {
            hexS = hexS.replace("1234567140420287", "1234567" + serial);
            hexS = hexS.replace("FFFF0140420287", "FFFFF" + serial);
//            hexS = hexS.replace("LLLL", "1200");
            hexS = hexS.replace("LLLL", "1400");
        } else if (factoryName.equalsIgnoreCase("瑞纳") || factoryName.equalsIgnoreCase("君沛")) {
            hexS = hexS.replace("1234567140420287", "12345678" + serial);
            hexS = hexS.replace("FFFF0140420287", "111100" + serial);
//            hexS = hexS.replace("LLLL", "1000");
//            hexS = hexS.replace("LLLL", "1200");
            hexS = hexS.replace("LLLL", "2E00"); //张胖子:协议编号改成46试试  16是贝特协议
//            hexS = hexS.replace("LLLL", "0010");
        } else if (factoryName.equalsIgnoreCase("中润")) {
            hexS = hexS.replace("1234567140420287", "12345678" + serial);
            hexS = hexS.replace("FFFF0140420287", "111100" + serial);
            hexS = hexS.replace("LLLL", "0400");
        } else if (factoryName.equalsIgnoreCase("测试")) {
            hexS = hexS.replace("1234567140420287", "12345678" + serial);
            hexS = hexS.replace("FFFF0140420287", "000000" + serial);
            hexS = hexS.replace("LLLL", "0F00");
        } else if (factoryName.equalsIgnoreCase("天罡")) {
            hexS = hexS.replace("1234567140420287", "12345678" + serial);
            hexS = hexS.replace("FFFF0140420287", "111100" + serial);
            hexS = hexS.replace("LLLL", "1200");
        } else if (factoryName.equalsIgnoreCase("泰安汉阳")) {
            hexS = hexS.replace("1234567140420287", "12345678" + serial);
            hexS = hexS.replace("FFFF0140420287", "000000" + serial);
            hexS = hexS.replace("LLLL", "7200");
        }
//        else if (factoryName.equalsIgnoreCase("河南新天")) {
//            hexS = hexS.replace("1234567140420287", "1234" + serial);
//            hexS = hexS.replace("FFFF0140420287", "00" + serial);
//            hexS = hexS.replace("LLLL", "9700");
//        }
        requestData = ByteUtil.hexStringToByte(hexS);
//        String s = ByteUtil.byteToHexString(requestData, 0, requestData.length);
//        System.out.println(s);
        requestData[requestData.length - 2] = ByteUtil.sum(requestData, 6, 89);
        setHaveResult(true);
    }

    public void readHeatMeter188(String meterNo) {
        requestData = new byte[19];
        requestData[0] = (byte) 0xfe;
        requestData[1] = (byte) 0xfe;
        requestData[2] = (byte) 0xfe;
        requestData[3] = (byte) 0x68;
        requestData[4] = (byte) 0x20;
        ByteUtil.stringToBcd(requestData, meterNo, 5, false);
        requestData[12] = 1;
        requestData[13] = 3;
        requestData[14] = 0x1f;
        requestData[15] = (byte) 0x90;
        requestData[16] = 0x12;
        requestData[17] = ByteUtil.sum(requestData, 3, 14);
        requestData[18] = 0x16;
        setHaveResult(true);
    }

    public void readValve188(String valveNo) {
        requestData = new byte[19];
        requestData[0] = (byte) 0xfe;
        requestData[1] = (byte) 0xfe;
        requestData[2] = (byte) 0xfe;
        requestData[3] = (byte) 0x68;
        requestData[4] = (byte) 0x41;
        ByteUtil.stringToBcd(requestData, valveNo, 5, false);
        requestData[12] = 1;
        requestData[13] = 3;
        requestData[14] = (byte) 0xf1;
        requestData[15] = (byte) 0x90;
        requestData[16] = 0x12;
        requestData[17] = ByteUtil.sum(requestData, 3, 14);
        requestData[18] = 0x16;
        setHaveResult(true);
    }

    public void setValve188Open(String valveNo, int open, boolean lock) {
        requestData = new byte[21];
        requestData[0] = (byte) 0xfe;
        requestData[1] = (byte) 0xfe;
        requestData[2] = (byte) 0xfe;
        requestData[3] = (byte) 0x68;
        requestData[4] = (byte) 0x41;
        ByteUtil.stringToBcd(requestData, valveNo, 5, false);
        requestData[12] = 4;
        requestData[13] = 5;
        requestData[14] = (byte) 0xf1;
        requestData[15] = 4;
        requestData[16] = 0;
        requestData[17] = (byte) (lock ? 0xff : 0);
        requestData[18] = (byte) open;
        requestData[19] = ByteUtil.sum(requestData, 3, 16);
        requestData[20] = 0x16;
        setHaveResult(true);
    }

    public void setValve188TempLimit(String valveNo, int tempUp, int tempDown) {
        requestData = new byte[23];
        requestData[0] = (byte) 0xfe;
        requestData[1] = (byte) 0xfe;
        requestData[2] = (byte) 0xfe;
        requestData[3] = (byte) 0x68;
        requestData[4] = (byte) 0x41;
        ByteUtil.stringToBcd(requestData, valveNo, 5, false);
        requestData[10] = 0x11;
        requestData[11] = 0x11;
        requestData[12] = 4;
        requestData[13] = 7;
        requestData[14] = (byte) 0xf1;
        requestData[15] = 5;
        requestData[16] = 0;
        requestData[17] = 0;
        requestData[18] = (byte) Integer.parseInt(String.valueOf(tempUp), 16);
        requestData[19] = 0;
        requestData[20] = (byte) Integer.parseInt(String.valueOf(tempDown), 16);
        requestData[21] = ByteUtil.sum(requestData, 3, 18);
        requestData[22] = 0x16;
    }

    public void readHeatMeter(String meterNo) {
        this.readEqu(meterNo);
    }

    public void readHouseValve(String valveNo) {
        this.readEqu(valveNo);
    }

    private void readOneData(String equNo) {
        int i = 0;
        requestData = new byte[]{0x68, 0, 0, 0, 0, 0x68
                , 0
                , 0x02, 0x37, 0x01, 0, 0
                , 0
                , 0
                , 0, 0
                , 0x20, 0x03
                , 0, 0, 0, 0x01
                , 0, 0, 0, 0, 0, 0, 0, 0,
                0,
                0x16};
        int l = requestData.length - 8;
        requestData[i++] = 0x68;
        requestData[i++] = (byte)(l & 0xff);
        requestData[i++] = (byte)(l >> 8 & 0xff);
        requestData[i++] = (byte)(l & 0xff);
        requestData[i++] = (byte)(l >> 8 & 0xff);
        requestData[i++] = 0x68;

        requestData[i++] = 0x41;
        i += 5;
        requestData[i++] = 0x0C;
        requestData[i++] = (byte) 0xF0;

        byte[] pnBytes = RunaFrameSequence.pnToBin(0);
        for (byte b : pnBytes) {
            requestData[i++] = b;
        }

        byte[] fnBytes = RunaFrameSequence.fnToBin(30);
        for (byte b : fnBytes) {
            requestData[i++] = b;
        }

        String sn = "1";
        while (sn.length() < 8) {
            sn = "0" + sn;
        }
        byte[] snBytes = ByteUtil.hexStringToByte(sn);
        for (byte b : snBytes) {
            requestData[i++] = b;
        }

//        while (equNo.length() < 16) {
//            equNo = "0" + equNo;
//        }
        if (equNo.length() < 16) {
            int n = 16 - equNo.length();
            for (int j = n; j > 0; j--) {
                equNo = j + equNo;
            }
        }
        byte[] equNoBytes = ByteUtil.hexStringToByte(equNo);
        for (byte b : equNoBytes) {
            requestData[i++] = b;
        }
        requestData[i++] = ByteUtil.sum(requestData, 6, i - 6);
        requestData[i++] = 0x16;
        setHaveResult(true);
    }

    private void readEqu(String equNo) {
        //30 66 06 02
        //68 18 00 18 00 68 41 02 37 01 00 00 0C F0 00 00 20 03 00 00 00 01 12 34 56 78 30 66 06 02 4D 16
        requestData = new byte[]{0x68, 0x18, 0, 0x18, 0, 0x68,  //6
                0x41, 0x02, 0x37, 0x01, 0, 0, 0x0C, (byte) 0xF0, 0, 0, 0x20, 0x03, 0, 0, 0, 0x01, 0x12, 0x34, 0x56,//19
                0x78, 0, 0, 0, 0, //5
                0,
                0x16};
        int length = equNo.length();
        int forLen = length / 2;
        int surplus = length % 2;

        int serialIndex = 30;
        for (int j = 0; j < forLen; j++) {
            requestData[--serialIndex] = (byte) Integer.parseInt(equNo.substring(length - (j + 1) * 2, length - (j * 2)), 16);
        }
        if (surplus != 0) {
            String i = ByteUtil.byteToHexString(requestData[--serialIndex]).substring(0, 1);
            String value = String.valueOf(Integer.parseInt(equNo.substring(0, 1)));
            requestData[serialIndex] = (byte) Integer.parseInt(i + value, 16);
        }
        requestData[30] = ByteUtil.sum(requestData, 6, 24);
        setHaveResult(true);
    }

    public void readBuildValve(int slave, boolean isLora, String serial) {
        requestData = new byte[]{(byte) slave, 3, 0, 9, 0, 0x2c, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        requestData = isLora ? ByteUtil.merge(new byte[]{(byte) 0xf9},
                ByteUtil.hexStringToByteFlip(serial), requestData) : requestData;
        setHaveResult(true);
        checkInterface = data -> {
            RunaConcenResponseData responseData = (RunaConcenResponseData) data;
            if (responseData.getData().get(0) instanceof ValveVO) {
                ValveVO valveVO = (ValveVO) responseData.getData().get(0);
                return serial.equals(valveVO.getValveSerial());
            }
            return false;
        };
    }

    public void sentBuildValveModel(String serial, boolean isLora, boolean openOrTemp) {
        int slave = Integer.parseInt(serial.substring(serial.length() - 3));
        slave = slave > 246 ? Integer.parseInt(serial.substring(serial.length() - 2)) : slave;
        requestData = new byte[]{(byte) slave, 6, 0, 0x0E, 0, (byte) (openOrTemp ? 0 : 6), 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        requestData = isLora ? ByteUtil.merge(new byte[]{(byte) 0xf9}, ByteUtil.hexStringToByteFlip(serial), requestData) : requestData;
        setHaveResult(true);
    }

    public void sentBuildValveOpen(String serial, boolean isLora, int open) {
        int slave = Integer.parseInt(serial.substring(serial.length() - 3));
        slave = slave > 246 ? Integer.parseInt(serial.substring(serial.length() - 2)) : slave;
        requestData = new byte[]{(byte) slave, 6, 0, 9, (byte) open, 0x5a, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        requestData = isLora ? ByteUtil.merge(new byte[]{(byte) 0xf9}, ByteUtil.hexStringToByteFlip(serial), requestData) : requestData;
        setHaveResult(true);
    }

    public void sentLoraValveTemp(String serial, float temp) {
        int slave = Integer.parseInt(serial.substring(serial.length() - 3));
        slave = slave > 246 ? Integer.parseInt(serial.substring(serial.length() - 2)) : slave;
        requestData = new byte[]{(byte) slave, 6, 0, 0x18, 0, 0, 0, 0};
        ByteUtil.shortToByte((short) (temp * 100), requestData, 4, ByteOrder.BA);
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        requestData = ByteUtil.merge(new byte[]{(byte) 0xf9}, ByteUtil.hexStringToByteFlip(serial), requestData);
        setHaveResult(true);
    }

    public void sentLoraValveModel(String serial, int model) {
        int slave = Integer.parseInt(serial.substring(serial.length() - 3));
        slave = slave > 246 ? Integer.parseInt(serial.substring(serial.length() - 2)) : slave;
        requestData = new byte[]{(byte) slave, 6, 0, 0xe, (byte) model, 0, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        requestData = ByteUtil.merge(new byte[]{(byte) 0xf9}, ByteUtil.hexStringToByteFlip(serial), requestData);
        setHaveResult(true);
    }

    public void changeAddress(String netEquNo, String ip, int port) {
        String hex = "68 14 01 14 01 68 " +
                "41 02 37 01 00 00 04 ff 00 00 01 02 11 22 33 44 " +
                "31 32 33 34 35 36 37 38 " +
                "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 05 00 01 00 " +
                "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " +
                "01 00 " +
                "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " +
                "F7 16";
        this.requestData = ByteUtil.hexStringToByte(hex.replace(" ", ""));
        System.arraycopy(netEquNo.getBytes(), 0, this.requestData, 22, 8);

        byte[] ipBytes = ip.getBytes();
        System.arraycopy(ipBytes, 0, this.requestData, 70, ipBytes.length);

        byte[] portBytes = ByteUtil.shortToByte((short) port);
        System.arraycopy(portBytes, 0, this.requestData, 102, portBytes.length);

        this.requestData[this.requestData.length - 2] = ByteUtil.sum(this.requestData, 6, this.requestData.length - 8);
    }


//    @Override
//    public boolean check(IResponseData data) {
//        if (data instanceof RunaConcenResponseData) {
//            RunaConcenResponseData responseData = (RunaConcenResponseData) data;
//            if (responseData.getAddress()!=null && responseData.getAddress().equals(address))
//                if (responseData.getData().get(0) instanceof HotMeterVO) {
//                    HotMeterVO hotMeterVO = (HotMeterVO) responseData.getData().get(0);
//                    return this.getRemain().toString().contains(hotMeterVO.getMeterSerial());
//                }
//        }
//        return true;
//    }


    public void readEquConfig(String serial) {
        byte[] bytes = new byte[100];
        int i = 0;

        bytes[i++] = 0x68;
        int lIndex = i;
        i += 4;
        bytes[i++] = 0x68;
        bytes[i++] = 0x41;

        String A1 = address.substring(0, 4);
        int A2;
        if (address.length()==8){//琅卡博
            A2 = Integer.parseInt(address.substring(4,8));
        }else {
            A2 = Integer.parseInt(address.substring(4,9));
        }

        byte[] area = new byte[5];
        char[] chars = A1.toCharArray();
        area[1] = (byte) ((chars[0] - 0x30<<4) | (chars[1] - 0x30)&0x0f);
        area[0] = (byte) ((chars[2] - 0x30<<4) | (chars[3] - 0x30)&0x0f);
        ByteUtil.shortToByte((short) A2, area, 2, ByteOrder.BA);
        area[4] = 0x02;

        for (byte b : area) {
            bytes[i++] = b;
        }

        bytes[i++] = 0x05;
        bytes[i++] = 0x70;

        bytes[i++] = 0x00;
        bytes[i++] = 0x00;
        bytes[i++] = 0x02;
        bytes[i++] = 0x01;

        bytes[i++] = 0x12;
        bytes[i++] = 0x34;
        bytes[i++] = 0x56;
        bytes[i++] = 0x78;

        bytes[i++] = 0x00;
        bytes[i++] = 0x00;


        byte[] serialBytes = ByteUtil.hexStringToByteFlip(serial);
        int len = serialBytes.length;
        for (int j = len - 1; j >= 0; j--) {
            bytes[i + 8 - len + j] = serialBytes[j];
        }
        System.out.println("查看配置: " + ByteUtil.byteToHexString(bytes));

        i += 8;
        int l = i - 6;
        bytes[lIndex++] = (byte)(l & 0xff);
        bytes[lIndex++] = (byte)(l >> 8 & 0xff);
        bytes[lIndex++] = (byte)(l & 0xff);
        bytes[lIndex++] = (byte)(l >> 8 & 0xff);

        bytes[i++] = ByteUtil.sum(bytes, 6, l);

        bytes[i++] = 0x16;

        this.requestData = new byte[i];
        System.arraycopy(bytes, 0, requestData, 0, i);

    }


    public void read(String equNo) {
        requestData = new byte[]{0x68, 0x18, 0, 0x18, 0, 0x68,  //6
                0x41, 0x02, 0x37, 0x01, 0, 0, 0x0C, (byte) 0x70, 0, 0, 0x20, 0x03, 0, 0, 0, 0x01, 0x12, 0x34, 0x56,//19
                0x78, 0, 0, 0, 0, //5
                0,
                0x16};
        int index = 7;
        RunaFrameSequence.Area area = new RunaFrameSequence.Area(address);
        for (byte b : area.getA()) {
            requestData[index++] = b;
        }

        int length = equNo.length();
        int forLen = length / 2;
        int surplus = length % 2;


        int serialIndex = 30;
        for (int j = 0; j < forLen; j++) {
            requestData[--serialIndex] = (byte) Integer.parseInt(equNo.substring(length - (j + 1) * 2, length - (j * 2)), 16);
        }
        if (surplus != 0) {
            String i = ByteUtil.byteToHexString(requestData[--serialIndex]).substring(0, 1);
            String value = String.valueOf(Integer.parseInt(equNo.substring(0, 1)));
            requestData[serialIndex] = (byte) Integer.parseInt(i + value, 16);
        }
        requestData[30] = ByteUtil.sum(requestData, 6, 24);
        setHaveResult(true);
    }

    @Override
    public boolean check(IResponseData data) {
        return checkInterface != null ? checkInterface.check(data) : super.check(data);
    }

    public static void main(String[] args) {
        LangKaBoEquRequestData requestData = new LangKaBoEquRequestData("63116040");
//        requestData.setNodeEquArchive("201605270102", "河南新天");
//        System.out.println("下发表号: " + ByteUtil.byteToHexString(requestData.getData()));

//        requestData.readEquConfig("201605270102");
//        System.out.println("查看配置: " + ByteUtil.byteToHexString(requestData.getData()));
//        requestData.read("201605270102");
//        requestData.readEqu("201605270102");
        requestData.readHeatMeter188("59493675");
        System.out.println("抄表: " + ByteUtil.byteToHexString(requestData.getData()));
    }
}
